package com.example.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.core.enums.AnnouncementStatusEnum;
import com.example.common.core.enums.ResultCode;
import com.example.common.security.exception.ServiceException;
import com.example.user.domain.announcement.Announcement;
import com.example.user.domain.announcement.es.AnnouncementES;
import com.example.user.elasticsearch.AnnouncementRepository;
import com.example.user.domain.announcement.dto.AnnouncementQueryDTO;
import com.example.user.domain.announcement.vo.AnnouncementDetailVO;
import com.example.user.domain.announcement.vo.AnnouncementVO;
import com.example.user.mapper.announcement.AnnouncementMapper;
import com.example.user.service.IAnnouncementService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Service
@Transactional(readOnly = true)
public class AnnouncementServiceImpl implements IAnnouncementService {
    @Autowired
    private AnnouncementMapper announcementMapper;
    
    @Autowired
    private AnnouncementRepository announcementRepository;

    @Override
    public List<AnnouncementVO> list(AnnouncementQueryDTO announcementQueryDTO) {
        // 先从ES中查询
        Sort sortBy = Sort.by(Sort.Direction.DESC, "createTime");
        Pageable pageable = PageRequest.of(announcementQueryDTO.getPageNum() - 1,
                announcementQueryDTO.getPageSize(), sortBy);
        Integer status = announcementQueryDTO.getStatus();
        String keyword = announcementQueryDTO.getTitle();
        Page<AnnouncementES> announcementESPage = null;

        try {
            if (status == null && StrUtil.isEmpty(keyword)) {
                // 查询全部数据
                announcementESPage = announcementRepository.findAll(pageable);
            } else if (StrUtil.isEmpty(keyword)) {
                // 根据状态筛选
                announcementESPage = announcementRepository.findAnnouncementByStatus(status, pageable);
            } else if (status == null) {
                // 根据关键词筛选
                announcementESPage = announcementRepository.findByTitleOrContent(keyword, keyword, pageable);
            } else {
                // 即根据关键词筛选，也根据状态进行筛选
                announcementESPage = announcementRepository.findByTitleOrContentAndStatus(keyword, keyword, status, pageable);
            }

            if (announcementESPage != null && announcementESPage.getTotalElements() > 0) {
                List<AnnouncementES> announcementESList = announcementESPage.getContent();
                List<AnnouncementVO> announcementVOList = BeanUtil.copyToList(announcementESList, AnnouncementVO.class);
                // 设置状态名称
                for (AnnouncementVO vo : announcementVOList) {
                    vo.setStatusName(AnnouncementStatusEnum.getDescByCode(vo.getStatus()));
                }
                return announcementVOList;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // ES查询未果，从数据库查询
        PageHelper.startPage(announcementQueryDTO.getPageNum(), announcementQueryDTO.getPageSize());
        List<AnnouncementVO> announcementVOList = announcementMapper.selectAnnouncementList(announcementQueryDTO);
        for (AnnouncementVO vo : announcementVOList) {
            vo.setStatusName(AnnouncementStatusEnum.getDescByCode(vo.getStatus()));
        }
        refreshQuestion();
        return announcementVOList;
    }
    
    private void refreshQuestion() {
        List<Announcement> questionList = announcementMapper.selectList(new LambdaQueryWrapper<Announcement>());
        if (CollectionUtil.isEmpty(questionList)) {
            return;
        }
        List<AnnouncementES> questionESList = BeanUtil.copyToList(questionList, AnnouncementES.class);
        // 将题目列表同步至es缓存中
        // 实体已经存在就更新，不存在就新增
        announcementRepository.saveAll(questionESList);
    }

    @Override
    public AnnouncementDetailVO detail(Long announcementId) {
        // 先从ES中查询
        try {
            AnnouncementES announcementES = announcementRepository.findById(announcementId).orElse(null);
            if (announcementES != null) {
                AnnouncementDetailVO announcementDetailVO = new AnnouncementDetailVO();
                BeanUtil.copyProperties(announcementES, announcementDetailVO);
                
                // 设置状态名称
                announcementDetailVO.setStatusName(AnnouncementStatusEnum.getDescByCode(announcementDetailVO.getStatus()));
                
                return announcementDetailVO;
            }
        } catch (Exception e) {
            e.printStackTrace();
            // ES查询异常，从数据库查询
        }
        
        // ES查询未果，从数据库查询
        AnnouncementDetailVO announcementDetailVO = announcementMapper.selectDetailsById(announcementId);
        if(announcementDetailVO == null){
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        
        // 设置状态名称
        announcementDetailVO.setStatusName(AnnouncementStatusEnum.getDescByCode(announcementDetailVO.getStatus()));
        
        // 从数据库查询的结果同步到ES（仅同步已发布的公告）
        try {
            if (AnnouncementStatusEnum.PUBLISHED.getCode().equals(announcementDetailVO.getStatus())) {
                AnnouncementES announcementES = new AnnouncementES();
                BeanUtil.copyProperties(announcementDetailVO, announcementES);
                announcementRepository.save(announcementES);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return announcementDetailVO;
    }

    @Override
    public String preAnnouncement(Long announcementId) {
        // 先不考虑缓存问题
        Long preAnnouncementId = announcementMapper.selectPreAnnouncement(announcementId);
        if(preAnnouncementId==null){
            return null;
        }
        return preAnnouncementId.toString();
    }

    @Override
    public String nextAnnouncement(Long announcementId) {
        Long nextAnnouncementId = announcementMapper.selectNextAnnouncement(announcementId);
        if(nextAnnouncementId==null){
            return null;
        }
        return nextAnnouncementId.toString();
    }
}
